package com.net.xpay.common.service.impl;

import com.net.xpay.common.domain.User;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.stat.UserTransMonthStat;
import com.net.xpay.common.domain.stat.UserTransStat;
import com.net.xpay.common.helper.NoticeHelper;
import com.net.xpay.common.manager.UserManager;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.stat.UserTransMonthStatManager;
import com.net.xpay.common.manager.stat.UserTransStatManager;
import com.net.xpay.common.model.UserTransStatMonthModel;
import com.net.xpay.core.constant.CoreConstant;
import com.net.xpay.core.manager.PayTransBatchManager;
import com.net.xpay.core.model.UserPayTransStatCommonModel;
import com.net.xpay.core.model.UserTransStatModel;
import com.net.common.util.LocalDateUtil;
import com.net.xpay.common.service.UserTransStatService;
import com.net.shard.ShardUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 net
 * @description: 用户转账统计业务层实现
net
 * @create: 2020-09-09 15:38
 **/
@Service
@Slf4j
public class UserTransStatServiceImpl implements UserTransStatService {

    @Autowired
    private UserTransStatManager userTransStatManager;

    @Autowired
    private UserTransMonthStatManager userTransMonthStatManager;

    @Autowired
    private UserManager userManager;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private PayTransBatchManager payTransBatchManager;

    @Autowired
    private NoticeHelper noticeHelper;

    /**
     * @param day: 当天的日期
     * @return void
     * @Description:[将user用户每天的转账金额和次数记录]
     * @author 
     * @date 2020/9/9 16:31
     */
    @Override
    public void doUserTransStat(LocalDate day) {
        // 调用UserManager获取所有的user
        List<User> userList = userManager.listAll();
        // 获取到userList中的id集合
        if (CollectionUtils.isEmpty(userList)) {
            log.warn("doUserSafePayTransStat There are no users at this time");
            return;
        }
        userList.forEach(user -> {
            Long userId = user.getId();
            UserTransStat userTransStat = new UserTransStat();
            // 通过userID获取到userShard
            UserShard userShard = userShardManager.getById(userId);
            try {
                // 先去判断该用户当天转账金额记录是否存在
                userTransStat.setDay(day);
                userTransStat.setYear(day.getYear());
                userTransStat.setMonth(day.getMonthValue());
                userTransStat.setUserId(userId);
                userTransStat.setPartnerId(user.getPartnerId());
                userTransStat.setFatherPartnerId(user.getFatherPartnerId());
                boolean exitRecord = hasStated(userTransStat);
                if (exitRecord) {
                    log.warn("doUserTransStat the record of userId={}|day={} is already exist", userId, day);
                    return;
                }
                // 切库处理
                ShardUtil.setShardContext(userShard.getShardId());
                // 获取当天的起始时间和终止时间 终止时间保留在23:59:59.999999999
                LocalDateTime minEndTime = LocalDateUtil.getDayStart(day);
                LocalDateTime maxEndTime = LocalDateUtil.getDayEnd(day);
                UserTransStatModel userTransStatModel = payTransBatchManager.countAmountAndTimesOfSuccess(userId, minEndTime, maxEndTime);
                BeanUtils.copyProperties(userTransStatModel, userTransStat);
                userTransStat.setFinalServicePrice(userTransStatModel.getServicePrice() - userTransStatModel.getRefund());

                //计费的批次数据
                UserPayTransStatCommonModel statCommonModel = payTransBatchManager.countNoFreeAmountAndTimesOfSuccess(userId, minEndTime, maxEndTime);
                userTransStat.setNotFreeSuccessAmount(statCommonModel.getSuccessAmount());
                userTransStat.setNotFreeSuccessCount(statCommonModel.getSuccessCount());

                // 数据入库
                userTransStatManager.save(userTransStat);
                //检查商户数据是否超过预警阈值
                checkUserTransStat(userTransStat);
            } finally {
                ShardUtil.cleanShardContext();
            }
        });
    }

    @Override
    public void doUserSafePayTransMonthStat(int year, int month) {
        // 调用UserManager获取所有的user
        List<User> userList = userManager.listAll();
        // 获取到userList中的id集合
        if (CollectionUtils.isEmpty(userList)) {
            log.warn("doUserSafePayTransMonthStat There are no users at this time");
            return;
        }
        userList.forEach(user -> {
            boolean exitRecord = hasMonthStated(year, month, user.getId());
            if (exitRecord) {
                log.warn("doUserSafePayTransMonthStat the record of userId={}|month={}|year={} is already exist", user.getId(), month, year);
                return;
            }
            List<UserTransStatMonthModel> userTransStatModels = userTransStatManager.sumMonthUserTransStat(year, month, user.getId());
            for (UserTransStatMonthModel monthModel : userTransStatModels) {
                Long userId = user.getId();
                UserTransMonthStat userTransStat = new UserTransMonthStat();
                userTransStat.setYear(year);
                userTransStat.setMonth(month);
                userTransStat.setUserId(userId);
                userTransStat.setPartnerId(monthModel.getPartnerId());
                userTransStat.setFatherPartnerId(monthModel.getFatherPartnerId());
                BeanUtils.copyProperties(monthModel, userTransStat);
                // 数据入库
                userTransMonthStatManager.save(userTransStat);
            }
        });
    }

    private boolean hasMonthStated(int year, int month, Long userId) {
        // 尝试通过时间加id获取数据
        UserTransMonthStat record = userTransMonthStatManager.findByMonthOfYear(year, month, userId);
        // 若果查到了数据，表示不需要在插入记录了
        return record != null;
    }

    private void checkUserTransStat(UserTransStat userTransStat) {
        try {
            if (userTransStat.getTotalCount() >= CoreConstant.TRANS_WARNING_COUNT) {
                noticeHelper.sendSystemInfoNotice("【预警】用户昨日转账笔数超过" + CoreConstant.TRANS_WARNING_COUNT + "笔，用户编号：" + userTransStat.getUserId(), "text");
            }
            if (new BigDecimal(userTransStat.getTotalTransAmount()).subtract(CoreConstant.TRANS_WARNING_MONEY).longValue() > 0) {
                noticeHelper.sendSystemInfoNotice("【预警】用户昨日转账额度超过" + CoreConstant.TRANS_WARNING_MONEY + "元，用户编号：" + userTransStat.getUserId(), "text");
            }
        } catch (Exception e) {
            log.error("checkUserTransStat error|userId={}", userTransStat.getUserId(), e);
        }
    }


    /**
     * @param userTransStat : 需要查询的数据
     * @return void
     * @Description:[判断userTransStat中是否已经存在了要插入的数据]
     * @author 
     * @date 2020/9/9 19:23
     */
    private boolean hasStated(UserTransStat userTransStat) {
        LocalDate day = userTransStat.getDay();
        Long userId = userTransStat.getUserId();
        // 尝试通过时间加id获取数据
        UserTransStat userTransStatRecord = userTransStatManager.findByDayAndUserId(day, userId);
        // 若果查到了数据，表示不需要在插入记录了
        return userTransStatRecord != null;
    }


}
